package main

import (
	"fmt"
	"github.com/jinzhu/gorm"
	"manageCrontab/config"
	"manageCrontab/db"
	"manageCrontab/lib"
	"manageCrontab/models"
	"reflect"
	"time"
)

var DB *gorm.DB
var MigrateFunc = map[string]reflect.Value{}

func main() {
	config.InitConfig("")
	db.Init()
	DB = db.GetDB()
	fmt.Println("初始化迁移数据...")
	InitMigrate()                   // 初始化
	if !DB.HasTable("Migrations") { // 判断迁移表是否存在
		fmt.Println("创建迁移表")
		DB.CreateTable(models.Migrations{})
	}

	haveMigrate := []models.Migrations{} // 已迁移方法数据初始化
	haveFuncMap := make(map[string]int)  // 初始化 组装已迁移的方法

	var migrate = models.Migrations{}
	// 获取最大执行批次
	DB.Order("batch desc").First(&migrate)

	// 开始迁移
	if MigrateOpreation == "on" {
		fmt.Println("开始迁移")

		// 获取所有已迁移的方法
		DB.Find(&haveMigrate)

		// 将已经迁移的方法放入集合
		for _, val := range haveMigrate {
			haveFuncMap[val.Migration] = val.ID
		}

		batch := migrate.Batch + 1
		for key, funcval := range MigrateFunc {
			migrate = models.Migrations{}
			// 判断方法是否已经执行过
			if _, ok := haveFuncMap[key]; ok {
				continue
			}
			// 执行方法并写入迁移表
			parms := []reflect.Value{reflect.ValueOf(1)} // 参数
			funcval.Call(parms)
			migrate.Migration = key
			migrate.Batch = batch
			migrate.CreatedAt = time.Now()
			migrate.UpdatedAt = time.Now()
			DB.Create(&migrate)
		}
		fmt.Println("迁移结束")
	}

	//回滚迁移
	if MigrateOpreation == "rollback" {
		fmt.Println("开始回滚")
		for i := 0; i < RollBackBatch; i++ {
			batch := migrate.Batch - i
			// 获取要回滚的方法, 这里需要排序，id大的先执行
			DB.Where("batch=?", batch).Order("id desc").Find(&haveMigrate)
			if len(haveMigrate) == 0 {
				continue
			}
			// 将要回滚的方法组装一下
			for _, val := range haveMigrate {
				haveFuncMap[val.Migration] = val.ID
			}

			for key, funcval := range MigrateFunc {
				// 判断方法是否已经执行过
				if _, ok := haveFuncMap[key]; !ok {
					continue
				}
				// 执行方法并写入迁移表
				parms := []reflect.Value{reflect.ValueOf(2)} // 参数
				funcval.Call(parms)
			}
			DB.Where("batch = ?", batch).Delete(&models.Migrations{})
		}
		fmt.Println("回滚结束")
	}
}

// @title 初始化迁移方法
func InitMigrate() {
	var migrate *Migrate
	vf := reflect.ValueOf(migrate)
	vft := vf.Type()
	numMethod := vf.NumMethod()
	for i := 0; i < numMethod; i++ {
		MigrateFunc[vft.Method(i).Name] = vf.Method(i)
	}
}

var MigrateOpreation = "on" // on 开始迁移， rollback 迁移回滚
//var MigrateOpreation = "rollback" // on 开始迁移， rollback 迁移回滚
var RollBackBatch = 1 // 回滚多少批次，默认回滚1次
type Migrate struct{}

// @title 创建表
// @param do_type 1 迁移，2 回滚
func (m *Migrate) CreateArticle(doType int) {
	if doType == 1 { // 迁移
		if !DB.HasTable(&models.Article{}) {
			// 在创建表的时候，会在 SQL 语句中拼接上 `"ENGINE=InnoDB"`
			//db.Set("gorm:table_options", "ENGINE=InnoDB").CreateTable(&User{})
			DB.Set("gorm:table_options", "ENGINE=InnoDB").CreateTable(&models.Article{})
		}
	}
	if doType == 2 { // 回滚
		DB.DropTableIfExists(&models.Article{})
	}
}

func (m *Migrate) CreateTask(doType int) {
	if doType == 1 { // 迁移
		if !DB.HasTable(&models.Task{}) {
			DB.Set("gorm:table_options", "ENGINE=InnoDB").CreateTable(&models.Task{})
		}
	}
	if doType == 2 { // 回滚
		DB.DropTableIfExists(&models.Task{})
	}
}

func (m *Migrate) CreateUser(doType int) {
	if doType == 1 { // 迁移
		if !DB.HasTable(&models.User{}) {
			DB.Set("gorm:table_options", "ENGINE=InnoDB").CreateTable(&models.User{})
		}
	}
	if doType == 2 { // 回滚
		DB.DropTableIfExists(&models.User{})
	}
}

func (m *Migrate) InsertDataUser(doType int) {
	if doType == 1 { // 迁移
		DB.Create(&models.User{Account: "admin", Password: lib.Md5Str("123456"), Role: 1, NickName: "超级管理员", Phone: "18774849189"})
	}
	if doType == 2 { // 回滚
		// 加上Unscoped()真删除
		DB.Unscoped().Delete(&models.User{Account: "admin"})
	}
}
